#include<bits/stdc++.h>
using namespace std;
const int MAXN = 25;
const int MOD = 1e9 + 7;
int dp[22][4194304];//dp[i][j]表示枚举到第j个状态时，前i个男生都有匹配的方案数
int a[MAXN][MAXN];
int count(int n){
	int cnt = 0;
	while(n){
		if(n & 1){
			cnt++;
		}
		n = n >> 1;
	}
	return cnt;
}
int main(){
	int n;
	cin >> n;
	for(int i = 1;i <= n;i++){
		for(int j = 1;j <= n;j++){
			cin >> a[i][j];
		}
	}
	//表示女生匹配的状态
	int m = 1 << n;
	//没有人相互匹配的方案有1种
	dp[0][0] = 1;
	//枚举前 i 个男生匹配 k 个女生的方案数
	for(int i = 1;i <= n;i++){
		//枚举所有的匹配状态，此时状态j表示有i对被匹配
		for(int j = 0;j < m;j++){
			//假设这个匹配状态和前 i 个男生已经匹配这件事不符合就跳过
			if(count(j) != i){
				continue;
			}
			//此时枚举到的S集合状态代表已经有 i 对了
			//此时枚举该状态的所有匹配的女生，必须是男女相容且应当要被匹配的
			for(int k = 1;k <= n;k++){
				//要第 i 个男生和第 k 个女生相容，并且第 k 个女生是我们选中准备匹配的
				if(a[i][k] && (j >> (k - 1) & 1)){
					//更新dp[i][j]的值，加上前 i-1 个男生和第 k 个女生未匹配的状态数
					//前 i-1 个男生和第 k 个女生未匹配的状态数用当前枚举到的状态j - (1 << (k - 1)）表示
					//这里的(1 << (k - 1)）表示状态表里，第k位女生为匹配的状态
					//j - (1 << (k - 1))是将当前匹配状态j中去掉第k个女生的匹配状态
					dp[i][j] = (dp[i][j] + dp[i - 1][j - (1 << (k - 1))]) % MOD;
				}
			}
		}
	}
	//输出前n个男生对于m种状态的匹配数
	cout << dp[n][m - 1] << "\n";
}